package com.jy.rhin.infra.repo.notfication.message.dao;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jy.rhin.config.infra.TranscationMessageProperties;
import com.jy.rhin.infra.repo.notfication.message.po.ReceiveMessageLogPo;
import com.jy.rhin.infra.repo.notfication.message.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ReceiveMessageLogDao {

    @Resource
    TranscationMessageProperties transcationMessageProperties;
    @Resource
    JdbcTemplate jdbcTemplate;
    String insert;

    public boolean existMd5(String md5){
        return Boolean.TRUE.equals(jdbcTemplate.query(ReceiveMessageLogPo.SCRIPT_EXIST_MD5, ResultSet::next, md5));
    }

    public void add(ReceiveMessageLogPo po){
        JSONObject json = (JSONObject) JSON.toJSON(po);
        jdbcTemplate.update(this.insert, json.keySet().stream().map(json::get).toArray(Object[]::new));
    }

    @PostConstruct
    public void init(){
        if(transcationMessageProperties.isCheckContext()){
            initTable();
        }
        initInsert();
    }

    void initInsert(){
        this.insert = "insert into " + ReceiveMessageLogPo.TABLE_NAME + "(#fields) values (#values)";
        ReceiveMessageLogPo po = new ReceiveMessageLogPo();
        JSONObject json = (JSONObject)JSON.toJSON(po);
        String fields = json.keySet().stream().map(StrUtil::toUnder).collect(Collectors.joining(","));
        String values = json.keySet().stream().map(s -> "?").collect(Collectors.joining(","));
        this.insert = this.insert.replace("#fields", fields).replace("#values", values);
    }

    void initTable(){
        createTable();
        checkAndUpdateField();
        checkAndAddIndex();
    }

    void createTable(){
        if(!existTable()){
            log.info("表结构不存在");
            try{
                this.jdbcTemplate.execute(ReceiveMessageLogPo.DdlReceiveMessasgeLog.CREATE.getSql());
                log.info("消息接收日志表创建成功:{}", ReceiveMessageLogPo.DdlReceiveMessasgeLog.CREATE.getSql());

            }catch (Exception e){
                log.error("消息接收日志表创建失败", e);
            }
        }else{
            log.info("表结构已存在");
        }
    }

    /**
     * 检查增加索引
     */
    void checkAndAddIndex(){
        String sql = "show indexes from t_receive_message_log";
        List<String> indexs = jdbcTemplate.query(sql, rs -> {
            List<String> list = new ArrayList<>();
            while (rs.next()) {
                String tableName = rs.getString(3);
                list.add(tableName);
            }
            return list;
        });
        if(!indexs.contains(ReceiveMessageLogPo.DdlReceiveMessasgeLog.INDEX_RECEIVE_TIME.getKey())){
            jdbcTemplate.execute(ReceiveMessageLogPo.DdlReceiveMessasgeLog.INDEX_RECEIVE_TIME.getSql());
            log.info("添加索引:{}", ReceiveMessageLogPo.DdlReceiveMessasgeLog.INDEX_RECEIVE_TIME.getSql());
        }
    }

    /**
     * 检查变更字段
     */
    void checkAndUpdateField(){
        String sql = "describe t_receive_message_log";
        List<String> fields = jdbcTemplate.query(sql, rs -> {
            List<String> list = new ArrayList<>();
            while (rs.next()) {
                String tableName = rs.getString(1);
                list.add(tableName);
            }
            return list;
        });
        if(!fields.contains(ReceiveMessageLogPo.DdlReceiveMessasgeLog.FIELD_EXTENSION.getKey())){
            this.jdbcTemplate.execute(ReceiveMessageLogPo.DdlReceiveMessasgeLog.FIELD_EXTENSION.getSql());
            log.info("添加字段:{}", ReceiveMessageLogPo.DdlReceiveMessasgeLog.FIELD_EXTENSION.getSql());
        }
    }

    boolean existTable(){
        String sql = "SHOW TABLES";
        List<String> tableNameList = jdbcTemplate.query(sql, rs -> {
            List<String> list = new ArrayList<>();
            while (rs.next()) {
                String tableName = rs.getString(1);
                list.add(tableName);
            }
            return list;
        });
        return tableNameList.contains(ReceiveMessageLogPo.TABLE_NAME);
    }
}
